package com.punai.common.core.domain;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.multi.ListValueMap;
import com.punai.common.core.domain.entity.SysDictData;
import com.punai.common.utils.DictUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class TreeBo {

    private String id;
    private String name;
    private String type;
    private String topId;

    private String pid;

    private String fbId;
    private String gxFbType;
    private String versionsId;
    private String code;
    private boolean disabled = false;
    private List<TreeBo> children = new ArrayList<>();

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public List<TreeBo> getChildren() {
        return children;
    }

    public void setChildren(List<TreeBo> children) {
        this.children = children;
    }

    public String getTopId() {
        return topId;
    }

    public void setTopId(String topId) {
        this.topId = topId;
    }

    public String getFbId() {
        return fbId;
    }

    public void setFbId(String fbId) {
        this.fbId = fbId;
    }

    public boolean isDisabled() {
        return disabled;
    }

    public void setDisabled(boolean disabled) {
        this.disabled = disabled;
    }

    public String getGxFbType() {
        return gxFbType;
    }

    public void setGxFbType(String gxFbType) {
        this.gxFbType = gxFbType;
    }

    public String getVersionsId() {
        return versionsId;
    }

    public void setVersionsId(String versionsId) {
        this.versionsId = versionsId;
    }


    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getPid() {
        return pid;
    }

    public void setPid(String pid) {
        this.pid = pid;
    }

    public static List<TreeBo> convert(List<? extends TreeParentBo> list, String defPid) {
        List<TreeBo> result = new ArrayList<>();
        ListValueMap<String, TreeParentBo> levelMap = new ListValueMap<>();
        for (TreeParentBo treeParentBo : list) {
            String pid = treeParentBo.getPid();
            levelMap.putValue(pid,treeParentBo);
        }
        List<TreeParentBo> roots = levelMap.get(defPid);
        if (CollUtil.isNotEmpty(roots)) {
            roots.sort(Comparator.comparing(TreeParentBo::getOrderNum));
            for (TreeParentBo root : roots) {
                TreeBo bo = new TreeBo();
                bo.setId(root.getId());
                bo.setName(root.getName());
                bo.setCode(root.getCode());
                bo.setPid(root.getPid());
                bo.setType(root.getType());
                bo.setTopId(root.getId());
                bo.setVersionsId(root.getVersionsId());
                result.add(bo);
                getTreeChildren(bo,levelMap,bo.getId(),true);
            }
        }
        return result;
    }

    public static List<TreeBo> convert(List<? extends TreeParentBo> list, String defPid,String gxFbType) {
        List<TreeBo> result = new ArrayList<>();
        ListValueMap<String, TreeParentBo> levelMap = new ListValueMap<>();
        for (TreeParentBo treeParentBo : list) {
            String pid = treeParentBo.getPid();
            levelMap.putValue(pid,treeParentBo);
        }
        List<TreeParentBo> roots = levelMap.get(defPid);
        if (CollUtil.isNotEmpty(roots)) {
            roots.sort(Comparator.comparing(TreeParentBo::getOrderNum));
            for (TreeParentBo root : roots) {
                TreeBo bo = new TreeBo();
                bo.setId(root.getId());
                bo.setName(root.getName());
                bo.setCode(root.getCode());
                bo.setType(root.getType());
                bo.setTopId(root.getId());
                bo.setPid(root.getPid());
                bo.setVersionsId(root.getVersionsId());
                bo.setGxFbType(gxFbType);
                result.add(bo);
                getTreeChildren(bo,levelMap,bo.getId(),false);
            }
        }
        return result;
    }


    public static List<TreeBo> convert(List<? extends TreeParentBo> list) {
        return convert(list, CommonConstants.DEF_PID);
    }
    private static void getTreeChildren(TreeBo bo, ListValueMap<String, TreeParentBo> levelMap,String topId,boolean isTop) {
        String id = bo.getId();
        List<TreeParentBo> chapters = levelMap.get(id);
        if (CollUtil.isNotEmpty(chapters)) {
            chapters.sort(Comparator.comparing(TreeParentBo::getOrderNum));
            List<TreeBo> children = bo.getChildren();
            for (TreeParentBo root : chapters) {
                TreeBo cbo = new TreeBo();
                if (!isTop) {
                    topId = root.getId();
                }
                cbo.setId(root.getId());
                cbo.setName(root.getName());
                cbo.setCode(root.getCode());
                cbo.setType(root.getType());
                cbo.setTopId(topId);
                cbo.setPid(root.getPid());
                cbo.setGxFbType(bo.getGxFbType());
                cbo.setVersionsId(root.getVersionsId());
                children.add(cbo);
                getTreeChildren(cbo,levelMap,topId,true);
            }
        }
    }

    public static List<TreeBo> sortConvert(List<? extends TreeParentBo> list) {
        List<TreeBo> resultTemporary = convert(list, CommonConstants.DEF_PID);
        List<TreeBo> result = new ArrayList<>();

        List<SysDictData> fee_projecttype = DictUtils.getDictCache("fee_projecttype");
        Map<String, TreeBo> resultMap = resultTemporary.stream().collect(Collectors.toMap(TreeBo::getId, Function.identity()));
        for (SysDictData sysDictData : fee_projecttype) {
            if(resultMap.containsKey(sysDictData.getDictValue())){
                result.add(resultMap.get(sysDictData.getDictValue()));
            }
        }
        return result;
    }

}
